package rc.work.module.bpm.service.problem;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import jakarta.annotation.Resource;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import rc.work.framework.security.core.util.SecurityFrameworkUtils;
import rc.work.module.bpm.api.task.BpmProcessInstanceApi;
import rc.work.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import rc.work.module.bpm.controller.admin.problem.vo.Edge;
import rc.work.module.bpm.controller.admin.problem.vo.Node;
import rc.work.module.bpm.controller.admin.problem.vo.ProblemBpmRespVO;
import rc.work.module.bpm.controller.admin.problem.vo.ProblemSaveVO;
import rc.work.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailReqVO;
import rc.work.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO;
import rc.work.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
import rc.work.module.bpm.dal.dataobject.problem.ProblemBpmDO;
import rc.work.module.bpm.dal.dataobject.problem.ProblemGroupDO;
import rc.work.module.bpm.dal.mysql.problem.ProblemBpmMapper;
import rc.work.module.bpm.dal.mysql.problem.ProblemGroupMapper;
import rc.work.module.bpm.service.definition.BpmProcessDefinitionService;
import rc.work.module.bpm.service.task.BpmProcessInstanceService;
import rc.work.module.bpm.service.task.BpmTaskService;
import rc.work.module.bpm.utils.SnowflakeIdGenerator;
import rc.work.module.system.api.dept.DeptApi;
import rc.work.module.system.api.dept.dto.DeptRespDTO;
import rc.work.module.system.api.user.AdminUserApi;
import rc.work.module.system.api.user.dto.AdminUserRespDTO;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

import static rc.work.framework.web.core.util.WebFrameworkUtils.getLoginUserId;

@Service
public class ProblemServiceImpl implements ProblemService {

    @Value("${result.table}")
    private String resultTable;

    @Resource
    private SnowflakeIdGenerator snowflakeIdGenerator;

    @Resource
    private ProblemGroupMapper problemGroupMapper;
    @Resource
    private ProblemBpmMapper  problemBpmMapper;

    @Resource
    private DeptApi deptApi;

    @Resource
    private AdminUserApi userApi;

    @Resource
    private BpmProcessInstanceApi processInstanceApi;

    @Resource
    private BpmProcessDefinitionService processDefinitionService;

    @Resource
    private BpmProcessInstanceService processInstanceService;

    @Resource
    private BpmTaskService bpmTaskService;



    public static final String PROCESS_KEY = "WTBL";
    public static final String PROCESS_KEY_WTSH = "WTSH";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProblem(ProblemSaveVO createReqVO) {

        //添加问题分组字段
        String upSql = "update " + resultTable +"."+createReqVO.getResultTable()+ " set INITIATIONTIME = SYSDATE , GROUP_ID = '%s',ISDEAL=%s where %s";
        String upZb = "update " + resultTable +"."+createReqVO.getResultTable()+ " set HCZT = '%s',CLQK='%s',FJSC='%s' where %s";


        //添加流程记录表
        ProblemBpmDO problemBpmDO = new ProblemBpmDO();
//        problemBpmDO.setInsId(createReqVO.getInsId());
        problemBpmDO.setBllx(createReqVO.getBllx());
        problemBpmDO.setFqsj(LocalDateTimeUtil.now());
        problemBpmDO.setFqrId(Objects.requireNonNull(SecurityFrameworkUtils.getLoginUserId()));
        problemBpmDO.setFqrName(SecurityFrameworkUtils.getLoginUserNickname());
        problemBpmDO.setFqrDeptId(SecurityFrameworkUtils.getLoginUserDeptId());
        DeptRespDTO checkedData1 = deptApi.getDept(problemBpmDO.getFqrDeptId()).getCheckedData();
        problemBpmDO.setFqrDeptName(checkedData1==null?"-":checkedData1.getName());
        problemBpmDO.setJsrId(createReqVO.getJsrId());
        AdminUserRespDTO checkedData = userApi.getUser(createReqVO.getJsrId()).getCheckedData();
        problemBpmDO.setJsrName(checkedData.getNickname());
        problemBpmDO.setJsrDeptId(checkedData.getDeptId());
        DeptRespDTO checkedData2 = deptApi.getDept(checkedData.getDeptId()).getCheckedData();
        problemBpmDO.setJsrDeptName(checkedData2==null?"-":checkedData2.getName());
        problemBpmDO.setBlyj(createReqVO.getBlyj());
        problemBpmDO.setDeptId(problemBpmDO.getDeptId());
        problemBpmMapper.insert(problemBpmDO);


        List<ProblemGroupDO> problemGroupDOList = new ArrayList<>();
        createReqVO.getParamsJson().forEach(param -> {
            AtomicReference<String> st = new AtomicReference<>(snowflakeIdGenerator.nextIdStr());
            Map<String, Object> map = JSON.parseObject(param).getJSONObject("queryParams").getInnerMap();
            StringJoiner sj = new StringJoiner(" and ");
            map.forEach((key, value) -> {
                if(key.equalsIgnoreCase("id") && value!=null && !value.equals("")){
                    ProblemGroupDO problemGroupDO = problemGroupMapper.selectById(Long.valueOf(value.toString()));
                    st.set(problemGroupDO==null?"":(problemGroupDO.getGroupId()==null?st.get():problemGroupDO.getGroupId()));
                }
                if(!key.equalsIgnoreCase("myId") && !key.equalsIgnoreCase("GROUP_ID")&& !key.equalsIgnoreCase("isGroup")&&!key.equalsIgnoreCase("id") && !key.equalsIgnoreCase("tableName")){
                    if(value!=null && !value.equals("null")){
                        sj.add(key + " = '" + value + "'");
                    }
                }
            });
            String up="";
            String uz = "";
            ProblemGroupDO problemGroupDO = new ProblemGroupDO();
            problemGroupDO.setStatus(1);
            if(createReqVO.getBllx().equals(1L)){
                up = String.format(upSql,st.get(),3, sj);
            }
            if(createReqVO.getBllx().equals(2L)){
                up = String.format(upSql,st.get(),1, sj);
                uz = String.format(upZb,createReqVO.getHczt(),createReqVO.getClqk(),createReqVO.getFjsc(), sj);
                problemGroupDO.setStatus(2);
            }
            if( !up.isEmpty()){
                problemGroupMapper.alter(up);
            }
            if(!uz.isEmpty()){
                problemGroupMapper.alter(uz);
            }
            //添加问题
            problemGroupDO.setProblemBpmId(problemBpmDO.getId());
//        problemGroupDO.setInsId(createReqVO.getInsId());
            problemGroupDO.setResultTable(createReqVO.getResultTable());
            problemGroupDO.setParams(param);
            problemGroupDO.setGroupId(st.get());
            problemGroupDO.setHczt(createReqVO.getHczt());
            problemGroupDO.setClqk(createReqVO.getClqk());
            problemGroupDO.setFjsc(createReqVO.getFjsc());
            problemGroupDOList.add(problemGroupDO);
        });
        problemGroupMapper.insertBatch(problemGroupDOList);

        if(createReqVO.getBllx().equals(1L)){
            //转办
            // 发起 BPM 流程
            Map<String, Object> processInstanceVariables = new HashMap<>();
            processInstanceVariables.put("type", 1);
            processInstanceVariables.put("dataId", problemBpmDO.getId());
            String processInstanceId = processInstanceApi.createProcessInstance(problemBpmDO.getFqrId(),
                    new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                            .setVariables(processInstanceVariables).setBusinessKey(problemBpmDO.getId().toString())
                            .setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees())).getCheckedData();
            problemBpmDO.setInsId(processInstanceId);
            problemBpmMapper.updateById(problemBpmDO);

            problemGroupDOList.forEach(problemGroupDO -> {
                problemGroupDO.setInsId(processInstanceId);
            });
            problemGroupMapper.updateBatch(problemGroupDOList);
        }

        if(CollectionUtils.isNotEmpty(createReqVO.getIds())){
            // 处理问题
            List<ProblemGroupDO> pgList = new ArrayList<>();
           createReqVO.getIds().forEach(id -> {
               ProblemGroupDO problemGroupDO = new ProblemGroupDO();
               problemGroupDO.setId(id);
               problemGroupDO.setStatus(2);
               pgList.add(problemGroupDO);
           });
            problemGroupMapper.updateBatch(pgList);
        }


        if(createReqVO.getBpmId()!=null){
            //查看这个流程表是否还有待处理的问题
            LambdaQueryWrapper<ProblemGroupDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProblemGroupDO::getProblemBpmId, createReqVO.getBpmId());
            queryWrapper.eq(ProblemGroupDO::getStatus, 1);
            List<ProblemGroupDO> problemGroupDO = problemGroupMapper.selectList(queryWrapper);
            if(CollectionUtils.isEmpty(problemGroupDO)){
                List<HistoricTaskInstance> taskListByProcessInstanceId = bpmTaskService.getTaskListByProcessInstanceId(problemBpmMapper.selectById(createReqVO.getBpmId()).getInsId(), true);
                if(!CollectionUtils.isEmpty(taskListByProcessInstanceId)){
                    for (HistoricTaskInstance task : taskListByProcessInstanceId) {
                        if(task.getEndTime()==null){
                            // 把这个流程处理掉
                            BpmTaskApproveReqVO reqVO = new BpmTaskApproveReqVO();
                            reqVO.setId(task.getId());
                            reqVO.setReason("流程自动通过结束");
                            bpmTaskService.approveTask(getLoginUserId(), reqVO);
                        }
                    }
//                    taskListByProcessInstanceId.forEach(task -> {
//                        if(task.getEndTime()==null){
//                            // 把这个流程处理掉
//                            BpmTaskApproveReqVO reqVO = new BpmTaskApproveReqVO();
//                            reqVO.setId(task.getId());
//                            reqVO.setReason("流程自动通过结束");
//                            bpmTaskService.approveTask(getLoginUserId(), reqVO);
//                        }
//                    });
                }
            }
        }


        if(createReqVO.getBllx().equals(2L)){
            //自办完成之后 需要原路返回
            // 获得所有流程节点
            LambdaQueryWrapper<ProblemGroupDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProblemGroupDO::getProblemBpmId, createReqVO.getBpmId());
            queryWrapper.last("limit 1");
            ProblemGroupDO problemGroupDO = problemGroupMapper.selectOne(queryWrapper);
            List<Node> bpmActivity = getBpmActivity(problemGroupDO.getGroupId());
            // 找到最后一个节点
            int size = bpmActivity.size();
            for (int i = size-1; i>=0; i--) {
                if(bpmActivity.get(i).getUserId().equals(getLoginUserId().toString())){
                        // 找到这个节点的前一个节点
                    if(i==0){
                        //表示自办自销了  不需要做任何操作
                        continue;
                    }else{
                        Node preNode = bpmActivity.get(i-1);

                        ProcessDefinition activeProcessDefinition = processDefinitionService.getActiveProcessDefinition(PROCESS_KEY_WTSH);
                        BpmApprovalDetailRespVO approvalDetail = processInstanceService.getApprovalDetail(getLoginUserId(), new BpmApprovalDetailReqVO() {{
                            setProcessDefinitionId(activeProcessDefinition.getId());
                        }});

                        List<BpmApprovalDetailRespVO.ActivityNode> activityNodes = approvalDetail.getActivityNodes();

                        Map<String, List<Long>> startUserSelectAssignees = new HashMap<>();
                        activityNodes.forEach(activityNode -> {
                                if(activityNode.getNodeType().equals(11)){
                                    startUserSelectAssignees.put(activityNode.getId(), List.of(Long.parseLong(preNode.getUserId())));
                                }
                        });

                        // 给这个账号发起一个回溯审核代办
                        // 发起 BPM 流程
                        Map<String, Object> processInstanceVariables = new HashMap<>();
                        processInstanceVariables.put("type", 1);
                        processInstanceVariables.put("dataId", problemBpmDO.getId());
                        String processInstanceId = processInstanceApi.createProcessInstance(problemBpmDO.getFqrId(),
                                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY_WTSH)
                                        // 这里采用拼接方式 后面的1 是为了让用户判断是否需要审核
                                        .setVariables(processInstanceVariables).setBusinessKey(problemBpmDO.getId().toString()+"_"+preNode.getUserId()+"_appro")
                                        .setStartUserSelectAssignees(startUserSelectAssignees)).getCheckedData();
                        problemBpmDO.setInsId(processInstanceId);
                    }


                }

            }




        }


        return problemBpmDO.getId();
    }

    @Override
    public Map<String, Object> getBpmHistoryForGraph(String groupId) {
        List<ProblemBpmRespVO> list = problemBpmMapper.getHistory(groupId);
        List<Node> nodes = new ArrayList<>();
        List<Edge> edges = new ArrayList<>();
        if (!list.isEmpty()) {
            nodes.add(new Node(snowflakeIdGenerator.nextIdStr(),"0", "开始","-", 1));
            //基于list构建点和边
            list.forEach(item -> {
                if(nodes.size()==1){
                    Node nextNode = new Node(snowflakeIdGenerator.nextIdStr(), item.getFqrId(), item.getFqrName(), item.getFqrDeptName(), 2);
                    if(item.getBllx()==1){
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(),nodes.get(0).getId(),nextNode.getId() , item.getBllx()==1?"转办":"自办"));
                        nodes.add(nextNode);
                        Node node = new Node(snowflakeIdGenerator.nextIdStr(), item.getJsrId(), item.getJsrName(), item.getJsrDeptName(), 2);
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(), nextNode.getId(), node.getId(), item.getBllx()==1?"转办":"自办"));
                        nodes.add(node);
                    }
                    if(item.getBllx()==2){
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(),nodes.get(0).getId(),nextNode.getId() , item.getBllx()==1?"转办":"自办"));
                        nodes.add(nextNode);
                        Node end = new Node(snowflakeIdGenerator.nextIdStr(),"0", "结束", "-", 1);
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(), nodes.get(nodes.size() - 1).getId(), end.getId(),"结束"));
                        nodes.add(end);
                    }
                }else{
                    if(item.getBllx()==1){
                        Node node = new Node(snowflakeIdGenerator.nextIdStr(), item.getJsrId(), item.getJsrName(), item.getJsrDeptName(), 2);
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(), nodes.get(nodes.size() - 1).getId(), node.getId(), item.getBllx()==1?"转办":"自办"));
                        nodes.add(node);
                    }
                    if(item.getBllx()==2){
                        Node end = new Node(snowflakeIdGenerator.nextIdStr(),"0", "结束", "-", 1);
                        edges.add(new Edge(snowflakeIdGenerator.nextIdStr(), nodes.get(nodes.size() - 1).getId(), end.getId(),"结束"));
                        nodes.add(end);
                    }
                }





            });
        }
        Map<String,Object> map = new HashMap<>();
        map.put("nodes",nodes);
        map.put("edges",edges);
        return map;
    }


    @Override
    public List<Node> getBpmActivity(String groupId) {
        List<ProblemBpmRespVO> list = problemBpmMapper.getHistory(groupId);
        List<Node> actityList = new ArrayList<>();
        Map<String,Boolean> isHave = new HashMap<>();
        if (!list.isEmpty()) {
            //基于list构建点和边
            list.forEach(item -> {
                if(isHave.get(item.getFqrId())==null){
                    isHave.put(item.getFqrId(),true);
                    actityList.add(new Node(snowflakeIdGenerator.nextIdStr(), item.getFqrId(), item.getFqrName(), item.getFqrDeptName(), 2));
                }
                if(isHave.get(item.getJsrId())==null){
                    isHave.put(item.getJsrId(),true);
                    actityList.add(new Node(snowflakeIdGenerator.nextIdStr(), item.getJsrId(), item.getJsrName(), item.getJsrDeptName(), 2));
                }
            });
        }
        return actityList;
    }

    @Override
    public Boolean appro(String insId) {

        List<HistoricTaskInstance> taskListByProcessInstanceId = bpmTaskService.getTaskListByProcessInstanceId(insId, true);
        if(!CollectionUtils.isEmpty(taskListByProcessInstanceId)){
            for (HistoricTaskInstance task : taskListByProcessInstanceId) {
                if(task.getEndTime()==null){
                    // 把这个流程处理掉
                    BpmTaskApproveReqVO reqVO = new BpmTaskApproveReqVO();
                    reqVO.setId(task.getId());
                    reqVO.setReason("流程自动通过结束");
                    bpmTaskService.approveTask(getLoginUserId(), reqVO);
                }
            }
        }

        return true;
    }
}
